-module(cloap_store).
-include_lib("stdlib/include/qlc.hrl").
-include("cloap_record.hrl").

-export([
  initdb/0, initdata/0, init_table/1
]).

-export([
         find_all/1, find_all/2,
         find_by_id/2,
         find/2,
         insert/1,
         delete/2, delete_all/1, delete_all/2,
         update/1,
         uuid/0, do/1
        ]).

-define(CreateTable(Table), init_table(Table) ->
               mnesia:create_table(Table, [{type, set},{disc_copies, [node()]},
                                           {attributes, record_info(fields, Table)}])).


% =========================================================
% @doc
% 初始化数据表，通常只运行一次
%
% <b style="color: red;">注意：运行时将会清除原有数据，请确认后再执行</b>
% @end
% =========================================================
?CreateTable(job);

?CreateTable(news_item);
?CreateTable(news_spider);

?CreateTable(config);
?CreateTable(app);
?CreateTable(uddi);
?CreateTable(acl);

?CreateTable(spider);
?CreateTable(todo_cache);
?CreateTable(app_config);
?CreateTable(user);
?CreateTable(user_process).




initdb() ->
    mnesia:stop(),
    mnesia:delete_schema([node()]),
    mnesia:create_schema([node()]),
    mnesia:start(),

    lists:foreach(fun(X) -> init_table(X) end,
                  [news_item, news_spider,
                   config, acl,
                   app, app_config, uddi,
                   spider, todo_cache,
                   user, user_process,
                   job]).



initdata() ->
    cloap_store:insert(#config{key = <<"title">>, descr = <<"平台主标题"/utf8>>, value = <<"创客集成办公平台"/utf8>>, mustbe = <<"true">>}),
    cloap_store:insert(#config{key = <<"subtitle">>, descr = <<"平台副标题"/utf8>>, value = <<"成都知一软件有限公司"/utf8>>, mustbe = <<"true">>}),

    cloap_store:insert(#acl{appid = <<"admin">>}).


find_all(Resource) ->
    do(qlc:q([Rec || Rec <- mnesia:table(Resource)])).
find_all(todo_cache, Who) ->
    do(qlc:q([Rec || Rec <- mnesia:table(todo_cache),
                     Rec#todo_cache.login == Who])).
find(user, {login, Login}) ->
    Users = do(qlc:q([Rec || Rec <- mnesia:table(user),
                             Rec#user.login =:= Login])),
    case Users of
        [] ->
            not_found;
        [H|_T] -> H
    end;
find(job, Keys) when is_list(Keys) ->
    Organ = proplists:get_value(organ, Keys),
    Subject = proplists:get_value(subject, Keys),
    lager:info("~p ~p", [Organ, Subject]),

    Jobs = do(qlc:q([Rec || Rec <- mnesia:table(job),
                            Rec#job.organ =:= Organ,
                            Rec#job.subject =:= Subject])),
    case Jobs of
        [] ->
            not_found;
        [H|_T] -> H
    end;
find(Table, Key) ->
    mnesia:dirty_read(Table, Key).

find_by_id(Resource, Id) ->
    do(qlc:q([Rec || Rec <- mnesia:table(Resource), Rec#spider.id == Id])). % Fixme: Rec#??? mustbe Macro
insert(Record) ->
    mnesia:dirty_write(Record).
update(Record) ->
    insert(Record).
delete(Table, Key) ->
    mnesia:dirty_delete(Table, Key).
delete_all(Table) ->
    [ mnesia:dirty_delete(Table, Rec) || Rec <- find_all(Table) ].
delete_all(todo_cache, Who) ->
    [ mnesia:dirty_delete(todo_cache, Rec#todo_cache.id) || Rec <- find_all(todo_cache),
                                  Rec#todo_cache.login == Who ].


do(Query) ->
  F = fun() -> qlc:e(Query) end,
  {atomic, Value} = mnesia:transaction(F),
  Value.

uuid() ->
  <<A:32, B:16, C:16, D:16, E:48>> = crypto:rand_bytes(16),
  Str = io_lib:format("~8.16.0b-~4.16.0b-4~3.16.0b-~4.16.0b-~12.16.0b",
                      [A, B, C band 16#0fff, D band 16#3fff bor 16#8000, E]),
  list_to_binary(Str).
